// 浏览器兼容的 Web Crypto API 实现
// 注意：某些 Node.js 特定功能在浏览器中不可用，已做相应调整

// 加密配置接口
export interface CryptoConfig {
  key?: string
  iv?: string
  algorithm?: 'aes-256-cbc' | 'aes-256-ecb' | 'des-cbc' | 'des-ecb'
}

// 默认加密配置
const DEFAULT_CONFIG: CryptoConfig = {
  algorithm: 'aes-256-cbc'
}

// 统一的加密工具类
export class CryptoUtils {
  private static instance: CryptoUtils

  private constructor() {
    // 构造函数
  }

  public static getInstance(): CryptoUtils {
    if (!CryptoUtils.instance) {
      CryptoUtils.instance = new CryptoUtils()
    }
    return CryptoUtils.instance
  }

  // ===== 对称加密方法 =====
// 注意：浏览器 Web Crypto API 对称加密实现较复杂，建议使用服务端加密或在需要时添加第三方库

  // AES 加密 - 在浏览器中实现较复杂，建议使用服务端
  public async encryptAES(text: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('AES 加密在浏览器中实现较复杂，建议使用服务端加密或添加专门的加密库')
  }

  // AES 解密 - 在浏览器中实现较复杂，建议使用服务端
  public async decryptAES(encryptedText: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('AES 解密在浏览器中实现较复杂，建议使用服务端解密或添加专门的加密库')
  }

  // DES 加密 - 在浏览器中不可用
  public async encryptDES(text: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('DES 加密在浏览器中不可用，建议使用 AES 或在服务端实现')
  }

  // DES 解密 - 在浏览器中不可用
  public async decryptDES(encryptedText: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('DES 解密在浏览器中不可用，建议使用 AES 或在服务端实现')
  }

  // Triple DES 加密 - 在浏览器中不可用
  public async encryptTripleDES(text: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('Triple DES 加密在浏览器中不可用，建议使用 AES 或在服务端实现')
  }

  // Triple DES 解密 - 在浏览器中不可用
  public async decryptTripleDES(encryptedText: string, key: string, config: CryptoConfig = DEFAULT_CONFIG): Promise<string> {
    throw new Error('Triple DES 解密在浏览器中不可用，建议使用 AES 或在服务端实现')
  }

  // ===== 哈希算法方法 =====

  // SHA-256 哈希
  public async hashSHA256(text: string): Promise<string> {
    try {
      const encoder = new TextEncoder()
      const data = encoder.encode(text)
      const hashBuffer = await crypto.subtle.digest('SHA-256', data)
      const hashArray = Array.from(new Uint8Array(hashBuffer))
      return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
    } catch (error) {
      console.error('SHA-256哈希错误:', error)
      throw new Error('SHA-256哈希失败')
    }
  }

  // SHA-256 哈希（同步版本）- 在浏览器中无法真正同步，返回Promise
  public hashSHA256Sync(text: string): string {
    console.warn('hashSHA256Sync 在浏览器中是异步的，请使用 hashSHA256')
    // 在浏览器环境中无法真正同步，抛出错误或返回 Promise
    throw new Error('浏览器环境中 SHA-256 哈希必须是异步的，请使用 hashSHA256')
  }

  // SHA-512 哈希
  public async hashSHA512(text: string): Promise<string> {
    try {
      const encoder = new TextEncoder()
      const data = encoder.encode(text)
      const hashBuffer = await crypto.subtle.digest('SHA-512', data)
      const hashArray = Array.from(new Uint8Array(hashBuffer))
      return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
    } catch (error) {
      console.error('SHA-512哈希错误:', error)
      throw new Error('SHA-512哈希失败')
    }
  }

  // SHA-512 哈希（同步版本）- 在浏览器中无法真正同步
  public hashSHA512Sync(text: string): string {
    console.warn('hashSHA512Sync 在浏览器中是异步的，请使用 hashSHA512')
    throw new Error('浏览器环境中 SHA-512 哈希必须是异步的，请使用 hashSHA512')
  }

  // SHA-1 哈希
  public async hashSHA1(text: string): Promise<string> {
    try {
      const encoder = new TextEncoder()
      const data = encoder.encode(text)
      const hashBuffer = await crypto.subtle.digest('SHA-1', data)
      const hashArray = Array.from(new Uint8Array(hashBuffer))
      return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
    } catch (error) {
      console.error('SHA-1哈希错误:', error)
      throw new Error('SHA-1哈希失败')
    }
  }

  // SHA-1 哈希（同步版本）- 在浏览器中无法真正同步
  public hashSHA1Sync(text: string): string {
    console.warn('hashSHA1Sync 在浏览器中是异步的，请使用 hashSHA1')
    throw new Error('浏览器环境中 SHA-1 哈希必须是异步的，请使用 hashSHA1')
  }

  // MD5 哈希 - Web Crypto API 不支持 MD5，需要使用第三方库或服务端实现
  public async hashMD5(text: string): Promise<string> {
    throw new Error('MD5 哈希在浏览器中不可用，请使用 SHA-256 或在服务端实现')
  }

  // MD5 哈希（同步版本）- 在浏览器中不可用
  public hashMD5Sync(text: string): string {
    throw new Error('MD5 哈希在浏览器中不可用，请使用 SHA-256 或在服务端实现')
  }

  // ===== 便捷方法 =====

  // 生成随机密钥
  public generateRandomKey(length: number = 32): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  }

  // 生成随机 IV
  public generateRandomIV(length: number = 16): string {
    return this.generateRandomKey(length)
  }

  // 密码加密函数：直接 RSA 加密，让后端处理哈希
  public async encryptPassword(password: string, publicKey?: string): Promise<string> {
    // 直接使用原始密码，让后端处理哈希
    if (publicKey) {
      const { rsaUtils } = await import('./rsa')
      return rsaUtils.encrypt(password)
    }
    
    // 如果没有公钥，直接返回原始密码（不推荐在生产环境中使用）
    return password
  }

  // 兼容旧的密码加密方法 - 现在使用 SHA-256 替代 MD5
  public async encryptPasswordWithMD5(password: string, publicKey?: string): Promise<string> {
    console.warn('encryptPasswordWithMD5 已弃用，使用 SHA-256 替代 MD5')
    // 使用 SHA-256 替代 MD5
    const hashedPassword = await this.hashSHA256(password)
    
    // 如果有公钥，进行 RSA 加密
    if (publicKey) {
      const { rsaUtils } = await import('./rsa')
      return rsaUtils.encrypt(hashedPassword)
    }
    
    // 如果没有公钥，直接返回 SHA-256 哈希值
    return hashedPassword
  }
}

// 导出单例实例
export const cryptoUtils = CryptoUtils.getInstance()

// ===== 便捷函数 =====

// AES 加密便捷函数
export const encryptAES = async (text: string, key: string, config?: CryptoConfig): Promise<string> => {
  return cryptoUtils.encryptAES(text, key, config)
}

// AES 解密便捷函数
export const decryptAES = async (encryptedText: string, key: string, config?: CryptoConfig): Promise<string> => {
  return cryptoUtils.decryptAES(encryptedText, key, config)
}

// DES 加密便捷函数
export const encryptDES = async (text: string, key: string, config?: CryptoConfig): Promise<string> => {
  return cryptoUtils.encryptDES(text, key, config)
}

// DES 解密便捷函数
export const decryptDES = async (encryptedText: string, key: string, config?: CryptoConfig): Promise<string> => {
  return cryptoUtils.decryptDES(encryptedText, key, config)
}

// SHA-256 哈希便捷函数
export const hashSHA256 = async (text: string): Promise<string> => {
  return cryptoUtils.hashSHA256(text)
}

// SHA-256 哈希便捷函数（同步版本）- 已弃用，请使用异步版本
export const hashSHA256Sync = (text: string): string => {
  console.warn('hashSHA256Sync 已弃用，请使用异步 hashSHA256 函数')
  throw new Error('浏览器环境中哈希必须是异步的，请使用 hashSHA256')
}

// MD5 哈希便捷函数 - 已弃用，请使用 SHA-256
export const hashMD5 = async (text: string): Promise<string> => {
  console.warn('hashMD5 已弃用，请使用 hashSHA256')
  throw new Error('MD5 哈希在浏览器中不可用，请使用 SHA-256')
}

// MD5 哈希便捷函数（同步版本）- 已弃用，请使用 SHA-256
export const hashMD5Sync = (text: string): string => {
  console.warn('hashMD5Sync 已弃用，请使用 hashSHA256')
  throw new Error('MD5 哈希在浏览器中不可用，请使用 SHA-256')
}

// 密码加密便捷函数
export const encryptPassword = async (password: string, publicKey?: string): Promise<string> => {
  return cryptoUtils.encryptPassword(password, publicKey)
}

// 兼容旧的密码加密便捷函数 - 已弃用
export const encryptPasswordWithMD5 = async (password: string, publicKey?: string): Promise<string> => {
  console.warn('encryptPasswordWithMD5 已弃用，请使用 encryptPassword')
  return cryptoUtils.encryptPasswordWithMD5(password, publicKey)
}